$(document).ready(function(){
	/*Check if a the user is logged in, if not redirect to login page
	* If the user is not logged in, alert and then redirect
	*/
	if( !checkLogin() ){
		alert("User is not logged in, click to redirect to login page.");
		window.location ='/index.html';
		return;	//return so no other code initializations are executed
	}
	
	bindButtons();	
			
 	Workspace.Init();
});


// Main workspace object
var Workspace = {
	
	Init: function(){		
		_self = this;
		_self.initVariables();
		_self.getAllReleases();		
		_self.bindPorletEffect();
		_self.bindStoryDetailOverlay();
		_self.addNewStoryListener();
		_self.bindDefectOnlyFields();
	},
	
	// Initialize any extra Workspace variables here
	initVariables : function() {
		
		//grab project id and release id
		_self._p_id = getParameterByName( '__pid' );
		_self._r_id = getParameterByName( '__rid' );
		
		if(_self._p_id == '' || _self._p_id == ''){
			alert('no project and release are specified, redirecting to selection page now');
			window.location = '/project-rev-switch.html';
		}
		
		//grab project name and release name
		
		callApi('projectApi', 'listProjects', 'POST', {}, function (resultObj) {
			if (resultObj.success) {
				_self._pname = resultObj.projects[_self._p_id];
				$('.main-header .project-name').html('Project : ' + _self._pname);	
			}
		},'','',false);
		
		
		callApi('projectApi', 'listReleases', 'POST', {projectId : _self._p_id}, function (resultObj) {
			if (resultObj.success) {
				_self._rname = resultObj.releases[_self._r_id];
				if(typeof _self._rname == 'undefined'){
					alert('no project and release are specified, redirecting to selection page now');
					window.location = '/project-rev-switch.html';
					return;
				}
				$('.main-header .release-name').html('Release : ' + _self._rname);	
					
			}
		},'','',false);
		
		// Initiate color picker
		$('#stickyColorPicker').colorPicker();
		
		// Determines whether a new user story can be added
		_self.lockAddUserStory = false;
		
		// Place holder column height
		_self.resizeHeight = 50;
		
		_self.lastUsedStickyType = 'story'; // TODO, make a choice on how this works
		_self.defaultStickyColor = '#D7DFEB';
		
		// Field Ids
		_self._stateIds = {};
		_self._defectIds = {};
		_self._priorityIds = {};
		_self._severityIds = {};
		_self._workStateNames = {};
		
		// Header and Content Char Length per Story
		_self._contentLen = 50;
		_self._headerLen = 10;
		
		
		//_self.getApiId('defect',_self._defectIds,'description');
		//_self.getApiId('priority',_self._priorityIds,'description');
		//_self.getApiId('severity',_self._severityIds,'description');
		_self.getApiId('state',_self._stateIds,'state_name');
		
		//translate database state/id into workspace state/id
		
	},

	// ----------------------------------------------------------------
	// Sticky functions
	// ----------------------------------------------------------------
	
	// Listen for clicks on the plus boxes to add new stories
	addNewStoryListener : function(){
		
		$(".workspace .plus-box").each(function(){
			$(this).click(function(){
				
				// Prevent user from adding a story if already editing one
				if (_self.lockAddUserStory == false) {
					_self.lockAddUserStory = true;
					
					var lastSticky = jQuery.parseJSON($(this).parent().children('.user-stories-wrap').children().last().find('.meta').html());
					
					//alert(lastSticky.ordering);
					
					// Add story placeholder to workspace
					var storyObj = {
						'state' : $(this).parent().parent().attr('id'),
						'state_name' : _self.getStateName($(this).parent().parent().attr('id')),
						'note' : '',
						'title' : ''
						//'ordering' : lastSticky? parseInt(lastSticky.ordering) + 1 : 1,
						//$(this).parent().children().length + 1
					};
					_self.addSticky(storyObj,true);
				}
			})
		});
	},
	
	addSticky : function(storyObj, userCreatedSticky){
		
		// Get state column
		var col = $('#'+storyObj.state);
		col.find('.user-stories-wrap').append(_self.createNewStoryHtml(storyObj));	
				
		var newStory = $('.workspace #new-story');
		newStory.removeAttr('id');

		this.attachEditStoryHandler(newStory);
		
        if (userCreatedSticky) {
            _self.setFormFields(); // Set form fields to default
            _self.hideUserFields(); // Hide fields if necessary
            newStory.addClass('active'); // Newly created, not yet 'saved'
            newStory.addClass('editing'); // Currently being edited
            _self._overlay.dialog('open');
			$('select[name=release]').val(_self._r_id);
            _self.editStoryContent(newStory, storyObj, true);
            _self.adjustColHeight(_self.resizeHeight);
            _self.bindToggle(newStory.find('.expand'));
        } else {
            newStory.find('.content').css("background-color", storyObj.color);
            newStory.find('.header').css("background-color", _self.lighten(storyObj.color));
        }
	},
	
	attachEditStoryHandler : function(el){
		
		$(el).find('.content').dblclick(function(){
			
			_self.lockAddUserStory = true;
			el.addClass('editing');

			// Get latest sticky data from database, incase other users made changes
			var id = $.parseJSON($(el).find('.meta').html()).sticky_id;
			
			callApi('stickyApi', 'getSticky', 'GET', {stickyId : id}, function(returnObj) {
				_self.showUserFields();
				_self.setFormFields(returnObj);
				_self._overlay.dialog('open');
				_self.editStoryContent(el, '', false);
			}, null, _self)
		});
	},
	
	getAllReleases : function(projectId) {
		
		callApi('projectApi', 'listReleases', 'GET', {projectId : _self._p_id}, function(returnObj) {
			
			//alert(JSON.stringify(returnObj.releases))
			if (returnObj.success) {
				_self._releases = returnObj.releases;
				_self.populateReleaseFields(returnObj.releases);
			}
		}, null, _self);
	},
	
	populateReleaseFields : function(releases) {
		
		var html = '<label>Release:</label>';
		html    += '<select name="release">';
		
		$.each(releases, function(key, val) {
			
			//alert(key.toString() + '  ' + val.toString())
			html += '<option value="' + key + '">' + val + '</option>';
			
		})
		
		html += '</select>';
		
		$('#release-select').html(html);
		$('select[name=release]').val(_self._r_id);
	},

	editStoryContent : function(storyHTML, story, isNew) {
		
		$('.ui-dialog .accept').unbind('click');
		$('.ui-dialog .delete').unbind('click');
		
		$('.ui-dialog .accept').click(function(){
			
			var stickyObj = _self.formToSticky(storyHTML, isNew, story);
			
			if(stickyObj.title == '' || stickyObj.note == ''){
				alert('Please do not leave either sticky title or description empty');
				return;
			}
			
			// Add/edit sticky in database
			isNew ? _self.addStickyToDatabase(storyHTML, stickyObj) : _self.editStickyInDatabase(stickyObj);

			// If this release belongs in the current workspace...
			if (stickyObj.release_id == _self._r_id) {
			
				// Set sticky HTML
				storyHTML.find('.title').html(_self.truncateText(stickyObj.title, _self._headerLen));
				storyHTML.find('.content').html(_self.truncateText(stickyObj.note, _self._contentLen));
				_self.setEditingStickyBackground(stickyObj.color);
				
				// Finished editing, save sticky
				$(storyHTML).parent().find('.active').removeClass('active');
				$(storyHTML).parent().find('.editing').removeClass('editing');
				
			} else {
				// Remove current user story from this page
				$(storyHTML).parent().find('.active').remove();
				$(storyHTML).parent().find('.editing').remove();
			}
			
			// Refresh UI
			_self._overlay.dialog('close');
			_self._sortable.sortable('refresh');
			_self.adjustColHeight(_self.resizeHeight);
			
			_self.lockAddUserStory = false;
			
			$('.ui-dialog .accept').unbind('click');
		});
		
		// Attach user story Close handler
		$('.ui-dialog .ui-dialog-titlebar-close,.field-row.close ').each(function(){
			$(this).click(function(){
					
					_self.lockAddUserStory = false;
					
					// Remove current user story.
					$(storyHTML).parent().find('.active').remove();
					
					// Refresh UI
					_self.adjustColHeight(_self.resizeHeight);
					_self._sortable.sortable('refresh');
								
			});
		});
		
		// Attach user story delete handler
		$('.ui-dialog .delete').click(function(){
			_self.lockAddUserStory = false;
			
			// Remove current user story.
			_self.removeSticky(storyHTML);
			
			// Refresh UI
			_self.adjustColHeight(_self.resizeHeight);
			_self._sortable.sortable('refresh');
			
			$('.ui-dialog .delete').unbind('click');
		});
	},
	
	// ----------------------------------------------------------------
	// Api calls
	// ----------------------------------------------------------------
	
	removeSticky : function(storyHTML){
		
		// Remove sticky by id
		var id = $.parseJSON(storyHTML.find('.meta').html()).sticky_id;
		
		callApi('stickyApi', 'removeSticky', 'POST', { stickyId : id }, function (resultObj) {
			if (resultObj.success) {
				$(storyHTML).remove();
				
				//TODO promote error msg
				_self._overlay.dialog('close');
				
				//TODO update priority here		
			}
		}, null, _self);
	},
	
	initializeStickies : function(){
	
		// Grab all stickies by id	
		callApi('projectApi', 'listStickies', 'GET', {releaseId : _self._r_id}, function(resultObj) {
			
			//_self.lastStickyId = resultObj.stickies[resultObj.stickies.length-1];

			// Get individual stickies using retreived id
			$.each(resultObj.stickies, function(key,sticky){
				
				_self.addSticky(_self.convertStickyFromDatabase(sticky), false);
				
				
				/*callApi('stickyApi', 'getSticky', 'GET', {stickyId : val}, function (resultObj) {
					
					// Make sure sticky has not been deleted
					if (resultObj.success && resultObj.is_deleted == '0') {
						_self.addSticky(_self.convertStickyFromDatabase(resultObj), false);
						
						// Adjust column height and bind collapse effect to stickies, once per column
						if(resultObj.sticky_id == _self.lastStickyId){
							_self.adjustColHeight(_self.resizeHeight);
							_self.bindToggleArray($(".workspace-content .user-story .header .expand"));
						}	
					}	
				}, null, null, false);*/ // False for a synchronous ajax call
			});
			
			// Adjust column height and bind collapse effect to stickies, once per column
			_self.adjustColHeight(_self.resizeHeight);
			_self.bindToggleArray($(".workspace-content .user-story .header .expand"));

		}, null, _self, false);
	},
	
	addStickyToDatabase: function (stickyHTML, stickyObj) {
		
	    callApi('stickyApi', 'addSticky', 'POST', stickyObj, function (resultObj, self) {
	        stickyObj.sticky_id = resultObj.sticky_id;
	        stickyHTML.parent().find('.meta').html(JSON.stringify(stickyObj));
	    }, null, _self)
	},
	
	editStickyInDatabase: function(stickyObj) {
        var id = $.parseJSON($('.editing .meta').html()).sticky_id;
        
		// Chain callbacks... until backend has addSticky return last_updated
		// First get the sticky by id for last_updated, then edit sticky
        callApi('stickyApi', 'getSticky', 'GET', {stickyId: id}, function(resultObj){
            stickyObj.stickyId = id;
            outboundObj = _self.trimStickyFields(stickyObj);
			outboundObj.last_updated = resultObj.last_updated;
            callApi('stickyApi', 'editSticky', 'POST', outboundObj, function(){
                $('.editing .meta').html(JSON.stringify(outboundObj))
            }, null, _self);
        }, null, _self);
	},
	
	// ----------------------------------------------------------------
	// Format conversion function
	// ----------------------------------------------------------------
	
	formToSticky: function (el, isNew, story) {
	    return {
	        'title': $('.ui-dialog .title input').val(),
	        'note': $('.ui-dialog .description textarea').val(),
	        'category': $('input:radio:checked').val(),
	        'color': $('#stickyColorPicker').val(),
	        'state_id': isNew ? _self._stateIds[story.state_name] : $.parseJSON($(el).parent().find('.editing').find('.meta').html()).state_id,
	        'priority_id': parseInt($('select[name=defect-priority]').val()),
	        'release_id': parseInt($('select[name=release]').val()),
	        'severity_id': parseInt($('select[name=defect-severity]').val()),
	        'defect_state_id': parseInt($('select[name=defect-state]').val()),
	        'last_updated': isNew ? '2011-05-23 20:16:04' : $.parseJSON($('.editing').find('.meta').html()).last_updated
	        //"ordering": $.parseJSON($(el).find('.meta').html()).ordering
	    }
	},
	
	// Converts a sticky from the database to a workspace-usable object
	convertStickyFromDatabase : function(databaseObj){
        return {
            "sticky_id": databaseObj.sticky_id,
            "category": databaseObj.category,
            "state_id": databaseObj.state_id,
            "priority_id": databaseObj.priority_id,
            "release_id": databaseObj.release_id,
            "note": databaseObj.note,
            "title": databaseObj.title,
            "color": databaseObj.color,
            "severity_id": databaseObj.severity_id,
            "defect_state_id": databaseObj.defect_state_id,
            "last_updated": databaseObj.last_updated,
            "state": _self._workStateNames[databaseObj.state_id],
            "author_name": databaseObj.author_name
            //"ordering": databaseObj.ordering
        };
	},
	
	// Create HTML from default object
	createNewStoryHtml : function(storyObj) {
		var storyHtml = '<div id="new-story" class = "user-story"><div class="header">';
			storyHtml += '<div class = "title">'+_self.truncateText(storyObj.title,_self._headerLen)+'</div>';
			storyHtml += '<div class = "expand">-</div>'
			storyHtml += '<div class="clear"></div></div>';
			storyHtml += '<div class="content">';
			storyHtml += _self.truncateText(storyObj.note,_self._contentLen);
			storyHtml += '</div>'
			storyHtml += '<div class="meta">'+JSON.stringify(storyObj)+'</div></div>';
		return storyHtml;
	},
	
	// Trim excess fields off a sticky object
	trimStickyFields : function(stickyObj) {
		return {
			'stickyId' : stickyObj.stickyId,
			'state_id' : stickyObj.state_id,
			'defect_state_id' : stickyObj.defect_state_id,
			'priority_id' : stickyObj.priority_id,
			'category' : stickyObj.category,
			'title' : stickyObj.title,
			'note' : stickyObj.note,
			'color' : stickyObj.color,
			'severity_id' : stickyObj.severity_id,
			'release_id' : stickyObj.release_id
		}
	},
	
	// ----------------------------------------------------------------
	// Helper functions
	// ----------------------------------------------------------------
	
	setEditingStickyBackground : function (color) {
		$('.editing .content').css("background-color", color);
		$('.editing .header').css("background-color", _self.lighten(color));
	},
	
	bindStoryDetailOverlay : function(){
		//start dialog
		$('.story-detail-overlap').dialog({
			width : 350,
			show : 'blind',
			draggable: true,
			title: 'Modify',
			autoOpen : false,
			closeText : 'Close',
			position : [$(window).width()/2-200,$(window).height()/2-200],
			open : function(){_self._sortable.sortable('disable')},
			close : function(){_self._sortable.sortable('enable')}
		});
		this._overlay = $('.story-detail-overlap');
		$('.field-row.close').click(function(){
			_self._overlay.dialog('close');
		});
	},	
	
	truncateText : function(text,length){
		if(text.length > length)
			return text.substring(text,length-1) + '...';
		else
			return text;	
	},
	
	bindPorletEffect : function(){

		this._sortable = $( ".workspace-content .user-stories-wrap" ).sortable({
			connectWith: ".workspace-content .user-stories-wrap",
			stop : function(event,ui){
				_self.changeStickyCol(ui);
				_self.adjustColHeight(_self.resizeHeight);	
			},
			cancel : '.expand'		
		});
		$(".workspace-content.user-stories-wrap" ).disableSelection();
	},
	
	// Change sticky column using moveSticky api
	changeStickyCol : function(ui){
		var stickyObj = ui.item;
		var state_name = $(stickyObj).parent().parent().parent().attr('id');
		
		//get state_id
		for(key in this._workStateNames){
			if(this._workStateNames[key] == state_name)
				var state_id = key;
		}
				
		var sticky = $.parseJSON(stickyObj.find('.meta').html());
		
		var param = {position : 'to',
					relativeTo : state_id,
					stickyId : sticky.sticky_id};
		
		// This function fires after the ajax call returns
		var callback = function(resultObj) {
			if (resultObj.success) {
				_self.changeStickyPosition(ui.item);
			}
		}
		callApi('stickyApi', 'moveSticky', 'GET', param, callback, null, _self);
		
	},
	
	changeStickyPosition : function(stickyObj){		
		var sticky = $.parseJSON(stickyObj.find('.meta').html());
		
		var index = $(stickyObj).index();
		var children_length = $(stickyObj).parent().children().length;
		
		if(children_length == 1)
			return;
		
		var position = '';
		var relativeSticky;
		
		if(index == children_length - 1){
			position = 'after';
			relativeSticky = $(stickyObj).parent().children()[index -1];
		}
		else{
			position = 'before';
			relativeSticky = $(stickyObj).parent().children()[index + 1];
		}
		
		relativeStickyObj = $.parseJSON($(relativeSticky).find('.meta').html());
		
		var param = {
			position : position,
			relativeTo : relativeStickyObj.sticky_id, //TODO: error here
			stickyId : sticky.sticky_id
		};
		
		
		callApi('stickyApi', 'moveSticky', 'GET', param, null, null, _self);
		
	},
	
	showDefectFields : function(time) {
		var fields = $('.field-rows-wrap .defect-wrap');
		if (time == 0)
			fields.show();
		else
			fields.show("blind", { direction: "vertical" }, time);
	},
	
	hideDefectFields : function(time) {
		var fields = $('.field-rows-wrap .defect-wrap');
		if (time == 0)
			fields.hide();
		else
			fields.hide("blind", { direction: "vertical" }, time);
	},
	
	showUserFields: function() {
		var fields = $('.field-rows-wrap .user-wrap');
		fields.show();
	},
	
	hideUserFields: function() {
		var fields = $('.field-rows-wrap .user-wrap');
		fields.hide();
	},
	
	bindDefectOnlyFields : function() {
		var defect = $('input:radio[value=defect]');
		var story = $('input:radio[value=story]');
		
		// Bind hide/show to radio buttons
		$(defect).click(function(){ _self.showDefectFields(200); });
		$(story).click(function(){ _self.hideDefectFields(200); });
		
		// Story is selected by default, hide fields
		_self.hideDefectFields(0);
	},
	
	setFormFields : function(sticky) {
		var type;
		var fields = $('.field-rows-wrap');
		var user = fields.find('.user-wrap');
		
		// Insert sticky values into form
		if (sticky) {
			
			// Title, description, release, type of sticky
			fields.find('.title input').val(sticky.title);
			fields.find('.description textarea').val(sticky.note);
			fields.find('.release select').val(sticky.release_id);
			fields.find('.radio-wrap input[value=' + sticky.category + ']').attr("checked", "checked");
			type = sticky.category; // Save category for later
			
			// Defect fields
			fields.find('select[name=defect-priority]').val(sticky.priority_id);
			fields.find('select[name=defect-severity]').val(sticky.severity_id);
			fields.find('select[name=defect-state]').val(sticky.defect_state_id);
			
			// User info fields
			user.find('#created').html(sticky.last_updated);
			user.find('#updated').html(sticky.last_updated);
			user.find('#owner').html(sticky.author_name); //TODO, call get again?
			
			// Color picker
			$("#stickyColorPicker").val(sticky.color);
			$("#stickyColorPicker").change();
		}
		// Set default values of form
		else {
			// Title, description, release, type of sticky
			fields.find('.title input').val('Title');
			fields.find('.description textarea').val('Description');
			fields.find('.release select').val(1);
			fields.find('.radio-wrap input[value=' + this.lastUsedStickyType + ']').attr("checked", "checked");
			type = this.lastUsedStickyType; // Save category for later
			
			// Defect fields
			fields.find('select[name=defect-priority]').val(1);
			fields.find('select[name=defect-severity]').val(1);
			fields.find('select[name=defect-state]').val(1);
			
			// User info fields
			user.find('#created').html('');
			user.find('#updated').html('');
			user.find('#owner').html('');
			
			// Color picker
			$("#stickyColorPicker").val(this.defaultStickyColor);
			$("#stickyColorPicker").change();
		}
		
		// Update fields to story/defect
		if ('defect' == type)
			this.showDefectFields(0);
		else 
			this.hideDefectFields(0);
		
	},
	
	bindToggleArray : function(el_array){
		$(el_array).each(function(){
			_self.bindToggle(this);
		});
	},
	
	assignUser : function() {
		
		var param = {
			"projectId" : 1,
			"users": [1,2,3,4]
		};
		
		callApi('projectApi', 'assignUser', 'GET', param, null, null, _self)
		
	},
	
	getApiId : function(field_name, arr, f_name){
		var para = {};
		para[field_name] = '';
		
		var callback = function(resultObj) {
			//parse state_name and id
			$.each(resultObj[field_name], function(key,val){
					var name = String(val[f_name]);
					arr[name.toLowerCase()] = key;
			});
			
			if(field_name == 'state')
				_self.workspaceStateName();
		}
		
		callApi('stickyApi', 'getId', 'GET', para, callback, null, _self);
		
		
	},
	
	getStateName : function(state){
		
		var state_name = '';
		
		switch(state){
			case 'requirements':
				state_name = String('requirement\/architecture');
				break;
			case 'development':
				state_name = String('development\/implementation');
				break;
			case 'code-review':
				state_name = 'code review';
				break;
			case 'api-review':
				state_name = 'api review';
				break;
			case 'unit-test':
				state_name = 'unit test';
				break;
			default:
				state_name = state;
				break;
			
		};
		
		return state_name;
	},	
	
	workspaceStateName : function(){
		for (key in _self._stateIds){
			var state_name = '';
			switch(key){
				case String('requirement\/architecture'):
					state_name = 'requirements';
					break;
				case String('development\/implementation'):
					state_name = 'development';
					break;
				case 'code review':
					state_name = 'code-review';
					break;
				case 'api review':
					state_name = 'api-review';
					break;
				case 'unit test':
					state_name = 'unit-test';
					break;
				default:
					state_name = key;
					break;
				
			};
			
			this._workStateNames[_self._stateIds[key]] = state_name; 
		}
		
		_self.initializeStickies();
	
	},
	
	// Takes a hex color #abcdef and returns a slightly lighter one
	lighten : function(color){
		
		// Get RGB
		var r = parseInt(color.slice(1, 3), 16);
		var g = parseInt(color.slice(3, 5), 16);
		var b = parseInt(color.slice(5, 7), 16);
		
		var colors = [r, g, b];  // Array of colors
		var color = '#';         // Color string to return
		
		for (var i in colors) {
			
			// Lighten values
			colors[i] += 15;
			
			// Set values to max if over
			if (colors[i] > 255)
				colors[i] = 255;
				
			// Turn values to 2 char strings
			colors[i] = colors[i].toString(16);
			if (colors[i].length < 2)
				colors[i] = '0' + colors[i];
				
			// Form string
			color += colors[i];
		};
		
		// Make sure color is the right length!
		if (color.length != 7) {alert('Color string must be length 7');}

		// Return lightened hex color
	    return color
  	},
	
	adjustColHeight : function(placeholderHeight){
		var maxColHeight = 0;

		$('.workspace-content .user-stories-wrap').each(function(){
			var colHeight = 0;
			
			// Sum height of column's children. Include padding, margin, etc.
			$.each($(this).children(), function(index, child){
  				colHeight += parseInt($(child).outerHeight(true));
			});
			
			// Set maxColHeight to height of tallest column
			if(colHeight > maxColHeight){
				maxColHeight = colHeight;
			}
		});
		
		// Animate workspace resize
		$(".workspace-content .user-stories-wrap").each(function(){
			$(this).animate( { height: maxColHeight+placeholderHeight }, 100, "easeOutQuad" );
		});
		
	},
	
    bindToggle: function(el){
        $(el).click(function(){
            var toggle = $(this);
            
            if (toggle.html() == '-') {
				$(this).parent().parent().find('.content').hide();
				toggle.html('+');
				toggle.css('top', '2px');
				toggle.parent().parent().addClass('minimized');
			}
			else {
				if (toggle.html() == '+') {
					$(this).parent().parent().find('.content').show();
					toggle.html('-');
					toggle.css('top', '-1px');
					toggle.parent().parent().removeClass('minimized');
				}
			}
            
            _self.adjustColHeight(_self.resizeHeight);
        });
    }
}
